/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "drawing_bench_test_base.h"
#include <string>
#include <fcntl.h>
#include "image/image.h"
#include "image_packer.h"
#include "pixel_map.h"
#include "utils/log.h"
using namespace std;
namespace OHOS {
namespace Rosen {
static std::shared_ptr<Drawing::ColorSpace> ColorSpaceToDrawingColorSpace(OHOS::Media::ColorSpace colorSpace)
{
    switch (colorSpace) {
        case OHOS::Media::ColorSpace::DISPLAY_P3:
            return Drawing::ColorSpace::CreateRGB(
                Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::DCIP3);
        case OHOS::Media::ColorSpace::LINEAR_SRGB:
            return Drawing::ColorSpace::CreateSRGBLinear();
        case OHOS::Media::ColorSpace::SRGB:
            return Drawing::ColorSpace::CreateSRGB();
        default:
            return Drawing::ColorSpace::CreateSRGB();
    }
}

static Drawing::ColorType PixelFormatToDrawingColorType(OHOS::Media::PixelFormat pixelFormat)
{
    switch (pixelFormat) {
        case OHOS::Media::PixelFormat::RGB_565:
            return Drawing::ColorType::COLORTYPE_RGB_565;
        case OHOS::Media::PixelFormat::RGBA_8888:
            return Drawing::ColorType::COLORTYPE_RGBA_8888;
        case OHOS::Media::PixelFormat::BGRA_8888:
            return Drawing::ColorType::COLORTYPE_BGRA_8888;
        case OHOS::Media::PixelFormat::ALPHA_8:
            return Drawing::ColorType::COLORTYPE_ALPHA_8;
        case OHOS::Media::PixelFormat::RGBA_F16:
            return Drawing::ColorType::COLORTYPE_RGBA_F16;
        case OHOS::Media::PixelFormat::UNKNOWN:
        case OHOS::Media::PixelFormat::ARGB_8888:
        case OHOS::Media::PixelFormat::RGB_888:
        case OHOS::Media::PixelFormat::NV21:
        case OHOS::Media::PixelFormat::NV12:
        case OHOS::Media::PixelFormat::CMYK:
        default:
            return Drawing::ColorType::COLORTYPE_UNKNOWN;
    }
}

static Drawing::AlphaType AlphaTypeToDrawingAlphaType(OHOS::Media::AlphaType alphaType)
{
    switch (alphaType) {
        case OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
            return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
        case OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
            return Drawing::AlphaType::ALPHATYPE_OPAQUE;
        case OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
            return Drawing::AlphaType::ALPHATYPE_PREMUL;
        case OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
            return Drawing::AlphaType::ALPHATYPE_UNPREMUL;
        default:
            return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
    }
}

void TestBase::SetCanvas(TestDisplayCanvas* canvas)
{
    playbackCanvas_ = canvas;
}

int TestBase::CreateBitmapCanvas()
{
    Media::InitializationOptions opts;
    opts.size.width = width_;
    opts.size.height = height_;
    opts.editable = true;
    std::unique_ptr<Media::PixelMap> pixelMap = Media::PixelMap::Create(opts);
    pixelMap_.reset(pixelMap.get());
    pixelMap.release();
    if (pixelMap_ == nullptr) {
        cout<<"TestBase::CreateBitmapCanvas() 3"<<endl;
        LOGE("failed to create pixelmap");
        return -1;
    }
    Drawing::BitmapFormat format {Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_OPAQUE};
    bitmap_.Build(width_, height_, format); // bitmap width and height
    OHOS::Media::ImageInfo imageInfo;
    pixelMap_->GetImageInfo(imageInfo);
    Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
        PixelFormatToDrawingColorType(imageInfo.pixelFormat),
        AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
        ColorSpaceToDrawingColorSpace(imageInfo.colorSpace) };
    bitmap_.SetInfo(drawingImageInfo);
    void* pixel = const_cast<void*>(reinterpret_cast<const void*>(pixelMap_->GetPixels()));
    if (pixel == nullptr) {
        LOGE("failed to GetPixels");
        return -1;
    }
    bitmap_.SetPixels(pixel);
    bitmapCanvas_ = std::make_shared<Drawing::Canvas>();
    if (bitmapCanvas_ == nullptr) {
        LOGE("failed to create bitmapCanvas");
        return -1;
    }
    bitmapCanvas_->Bind(bitmap_);
    bitmapCanvas_->DrawColor(background_);
    return 0;
}

int TestBase::BitmapCanvasToFile()
{
    OHOS::Media::ImagePacker imagePacker;
    std::set<std::string> formats;
    uint32_t ret = imagePacker.GetSupportedFormats(formats);
    if (ret != 0) {
        LOGE("failed to GetSupportedFormats");
        return -1;
    }

    std::string path = "/data/test/" + fileName_ + ".jpg";
    int32_t fileDes = open(path.c_str(), O_CREAT | O_RDWR );
    if (fileDes <= 0) {
        LOGE("failed to open");
        return -1;
    }

    OHOS::Media::PackOption option;
    option.format = "image/jpeg";
    uint32_t result = imagePacker.StartPacking(fileDes, option);
    if (result != 0) {
        LOGE("failed to StartPacking");
        close(fileDes);
        return -1;
    }
    result = imagePacker.AddImage(*pixelMap_);
    if (result != 0 ) {
        LOGE("failed to AddImage");
        close(fileDes);
        return -1;
    }
    int64_t packedSize = 0;
    result = imagePacker.FinalizePacking(packedSize);
    if (result != 0 ) {
        LOGE("failed to FinalizePacking");
        close(fileDes);
        return -1;
    }

    close(fileDes);
    return 0;
}

int TestBase::DiasplayToScreen()
{
    if (playbackCanvas_ == nullptr) {
        LOGE("playbackCanvas_ is null ");
        return -1;
    }
    playbackCanvas_->DrawColor(0xff000000); //black
    // Offset 100 * 100, skipping the rounded corner area of the screen
    playbackCanvas_->DrawBitmap(bitmap_, 0, 0);
    return 0;
}

void TestBase::SetFileName(std::string fileName)
{
    fileName_ = fileName;
}

void TestBase::SetTestCount(uint32_t count)
{
    testCount_ = count;
}

void TestBase::TestFunctionCpu()
{
    cout<<"TestBase::TestFunctionCpu() 1"<<endl;
    if (CreateBitmapCanvas() != 0) {
        cout<<"TestBase::TestFunctionCpu() 11"<<endl;
        return;
    }
    OnTestFunctionCpu(bitmapCanvas_.get());
    (void)DiasplayToScreen();
    (void)BitmapCanvasToFile();
}

void TestBase::TestPerformanceCpu()
{
    if (CreateBitmapCanvas() != 0) {
        return;
    }
    OnTestPerformanceCpu(bitmapCanvas_.get());
    (void)DiasplayToScreen();
}

void TestBase::TestFunctionGpuUpScreen()
{
    if (playbackCanvas_ == nullptr) {
        LOGE("playbackCanvas_ is null ");
        return;
    }
    OnTestFunctionGpuUpScreen(playbackCanvas_);
}

void TestBase::TestPerformanceGpuUpScreen()
{
    if (playbackCanvas_ == nullptr) {
        LOGE("playbackCanvas_ is null ");
        return;
    }
    OnTestPerformanceGpuUpScreen(playbackCanvas_);
}
} // namespace Rosen
} // namespace OHOS